﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Diagnostics.Contracts;
using System.Globalization;
using ShredTheLog.Api;
using System.ComponentModel.Composition;
using System.Text.RegularExpressions;
using ShredTheLog.Api.DataContracts;

namespace ShredTheLog.Converters
{
    [ValueConversion(typeof(object), typeof(string))]
    public sealed class RoomConverter : ConverterBase, IValueConverter
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var roomId = (string)value;
            Contract.Assume(!String.IsNullOrWhiteSpace(roomId));
            return Convert(roomId);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        public const string PublicRoomPrefix = "CR";
        public const string OtherRoomID = PublicRoomPrefix + "Other";
        public const string ScandinavianRoomID = PublicRoomPrefix + "Sca";
        public static readonly Dictionary<Language, string> LanguageCodes = new Dictionary<Language, string>() 
        {
            {Language.English, "En"},
            {Language.Spanish, "Sp"},
            {Language.Japanese, "Ja"},
            {Language.Portuguese, "Pt"},
            {Language.ChineseMandarin, "Ch"},
            {Language.Russian, "Ru"},
            {Language.French, "Fr"},
            {Language.Korean, "Ko"},
            {Language.Arabic, "Ar"},
            {Language.Italian, "It"},
            {Language.German, "Ge"},
            {Language.Turkish, "Tu"},
            {Language.Hindi, "Hi"},
            {Language.ChineseCantonese, "Ca"},
            {Language.Dutch, "Du"},
            {Language.Swedish, "Sw"},
            {Language.Thai, "Th"},
            {Language.Polish, "Po"},
            {Language.Hungarian, "Hu"},
        };


        private static readonly Regex PublicRoomNameExp = new Regex(@"^" + PublicRoomPrefix + "(?<Language1>[A-Z][a-z]+)(?<Language2>[A-Z][a-z]+)?$", RegexOptions.Compiled);
        private static readonly Regex PrivateRoomNameExp = new Regex(@"^(?<Caller>\d+)-(?<Callee>\d+)$", RegexOptions.Compiled);
        
        public string Convert(string roomId)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(roomId));
            Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));

            if (roomId.StartsWith(PublicRoomPrefix))
            {
                if (roomId == OtherRoomID)
                {
                    var result = ShredServices.GetLocalizedString("s_CROther");
                    Contract.Assume(!String.IsNullOrWhiteSpace(result));
                    return result;
                }
                else if (roomId == ScandinavianRoomID)
                {
                    var result = ShredServices.GetLocalizedString("s_CRSca");
                    Contract.Assume(!String.IsNullOrWhiteSpace(result));
                    return result;
                }
                else
                {
                    var matches = PublicRoomNameExp.Matches(roomId);
                    if (matches.Count == 1)
                    {
                        var languageString1 = matches[0].Groups["Language1"].Value;
                        if (LanguageCodes.Any(i => i.Value == languageString1))
                        {
                            Language language1 = LanguageCodes.Single(i => i.Value == languageString1).Key;
                            if (matches[0].Groups["Language2"].Success)
                            {
                                var languageString2 = matches[0].Groups["Language2"].Value;
                                if (LanguageCodes.Any(i => i.Value == languageString2))
                                {
                                    Language language2 = LanguageCodes.Single(i => i.Value == languageString2).Key;
                                    var result = String.Format("{0} - {1}", LanguagesConverter.Default.Convert(language1), LanguagesConverter.Default.Convert(language2));
                                    Contract.Assume(!String.IsNullOrWhiteSpace(result));
                                    return result;
                                }
                                else
                                {
                                    return roomId;
                                }
                            }
                            else
                            {
                                return LanguagesConverter.Default.Convert(language1);
                            }
                        }
                        else
                        {
                            return roomId;
                        }
                    }
                    else
                    {
                        return roomId;
                    }
                }
            }
            else
            {
                var matches = PrivateRoomNameExp.Matches(roomId);
                if (matches.Count == 1)
                {
                    var callerUid = int.Parse(matches[0].Groups["Caller"].Value);
                    var calleeUid = int.Parse(matches[0].Groups["Callee"].Value);
                    var textChatUsers = ShredServices.TextChatUsers;
                    var caller = textChatUsers != null ? textChatUsers.SingleOrDefault(i => i.Uid == callerUid) : null;
                    string callerName = caller != null ? caller.Name : callerUid.ToString(CultureInfo.InvariantCulture);
                    var callee = textChatUsers != null ? textChatUsers.SingleOrDefault(i => i.Uid == calleeUid) : null;
                    string calleeName = callee != null ? callee.Name : calleeUid.ToString(CultureInfo.InvariantCulture);
                    var result = String.Format("{0} - {1}", callerName, calleeName);
                    Contract.Assume(!String.IsNullOrWhiteSpace(result));
                    return result;
                }
                else
                {
                    return roomId;
                }
            }
        }

        public static readonly RoomConverter Default = new RoomConverter();
    }
}
